package com.pervasive.geoTagging;

import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.Looper;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

public class MarkerList extends ItemizedOverlay<OverlayItem>{

	public MarkerList(Activity a, Context context, Drawable defaultMarker, MapView mappa, HttpClient cl) {
		super(boundCenterBottom(defaultMarker));
		this.context = context;
		this.map = mappa;
		this.client = cl;
		this.activity = a;
	}

	protected OverlayItem createItem(int i) {
		return items.get(i);
	}

	public int size() {
		return items.size();
	}
	
	public void addOverlayItem(GeoPoint position, String martekTitle, String snippet){
		items.add(new OverlayItem(position, martekTitle, snippet));
		populate();
	}
	
	public boolean onTap(int index){
		MainActivity.createDirs();
		relation = new HashMap<String, String>();
		boolean isRecycled;
		GeoPoint point = createItem(index).getPoint();
		if (balloonView == null) {
			balloonView = new BalloonOverlay(context);
			clickRegion = (View) balloonView.findViewById(R.id.balloon_inner_layout);
			isRecycled = false;
		}
		else isRecycled = true;
		balloonView.setVisibility(View.GONE);
		List<Overlay> mapOverlays = map.getOverlays();
		if (mapOverlays.size() > 1) hideOtherBalloons(mapOverlays);
		balloonView.setData(createItem(index));
		MapView.LayoutParams params = new MapView.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, point,MapView.LayoutParams.BOTTOM_CENTER);
		params.mode = MapView.LayoutParams.MODE_MAP;
		setBalloonTouchListener(index);
		balloonView.setVisibility(View.VISIBLE);
		if(isRecycled) balloonView.setLayoutParams(params);
		else map.addView(balloonView, params);
		map.getController().animateTo(point);
		map.getController().setCenter(point);
		queryThread = new Thread(new Runnable(){
			public void run(){
				Looper.prepare();
					esitoQuery = false;
					String ip = MainActivity.pref.getString("IP", "localhost");
					if(!ip.equalsIgnoreCase("localhost")){
						HttpGet request = new HttpGet("http://"+ip+":8081/GeoTagWebService/LoadServlet?location="+balloonView.getTitleForQuery());
						ByteArrayOutputStream outstream = new ByteArrayOutputStream();
						HttpResponse res = null;
						try {
							res = client.execute(request);
						} catch (ClientProtocolException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						}
						if(res != null){
							esitoQuery = true;
						
							try {
								res.getEntity().writeTo(outstream);
							} catch (IOException e) {
								e.printStackTrace();
							}
							ByteArrayInputStream instream = new ByteArrayInputStream(outstream.toByteArray());
							DocumentBuilder bulder = null;
							try {
								bulder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
							} catch (ParserConfigurationException e) {
								e.printStackTrace();
							}
							Document document = null;
							try {
								document = bulder.parse(new InputSource(new InputStreamReader(instream, "UTF-8")));
							} catch (UnsupportedEncodingException e) {
								e.printStackTrace();
							} catch (SAXException e) {
								e.printStackTrace();
							} catch (IOException e) {
								e.printStackTrace();
							}
							Element loadInfo = document.getDocumentElement();
							Element listOfPhotos = (Element)loadInfo.getElementsByTagName("listOfPhotos").item(0);
							NodeList foto = listOfPhotos.getElementsByTagName("photo");
							Element listOfNodes = (Element)loadInfo.getElementsByTagName("listOfNotes").item(0);
							NodeList note = listOfNodes.getElementsByTagName("note");
							numeroFoto = foto.getLength();
							if(numeroFoto==0){
								MappaActivity.removeLocation(balloonView.getTitleForQuery());
								return;
							}
							activity.runOnUiThread(new Runnable(){
								public void run() {
									balloonView.setMax(numeroFoto);
								}
							});
							int numeroNote = note.getLength();
							for(int num = 0; num < numeroFoto && num < MAX; num++){
								final int finale = num;
								activity.runOnUiThread(new Runnable(){
									public void run() {
										balloonView.setProgress(finale);
									}
								});
								Element el = (Element)foto.item(num);
								Element path_foto = (Element)el.getElementsByTagName("uri").item(0);
								Element id_commento = (Element)el.getElementsByTagName("id_note").item(0);
								String comment_id = id_commento.getFirstChild().getNodeValue();
							    String nameFile = (num+1)+"perv";
								for(int x = 0; id_commento != null && x < numeroNote; x++){
									Element nota = (Element)note.item(x);
									if(nota.getElementsByTagName("id_note").item(0).getFirstChild().getNodeValue().equals(comment_id)){
										FileOutputStream file = null;
										try {
											file = new FileOutputStream(MainActivity.NOTES_DIR.getAbsolutePath()+"/"+nameFile+".txt");
										} catch (FileNotFoundException e) {
											e.printStackTrace();
										}
										BufferedWriter buf = new BufferedWriter(new PrintWriter(file));
										try {
											buf.write(nota.getElementsByTagName("text").item(0).getFirstChild().getNodeValue());
										} catch (DOMException e) {
											e.printStackTrace();
										} catch (IOException e) {
											e.printStackTrace();
										}
										try {
											buf.close();
										} catch (IOException e) {
											e.printStackTrace();
										}
										try {
											file.close();
										} catch (IOException e) {
											e.printStackTrace();
										}
										break;
									}
								}
								relation.put(nameFile+".jpeg", el.getElementsByTagName("id_photo").item(0).getFirstChild().getNodeValue());
								String uri = path_foto.getFirstChild().getNodeValue();
								InputStream is = null;
								try {
									is = fetch(uri);
								} catch (IOException e) {
									e.printStackTrace();
								}
								Bitmap image = BitmapFactory.decodeStream(is);
							    BitmapFactory.Options options = new BitmapFactory.Options();
							    options.inSampleSize = 1; 
							    FileOutputStream fileOutputStream = null;
								try {
									fileOutputStream = new FileOutputStream(MainActivity.PHOTOS_DIR.getAbsolutePath()+"/" + nameFile + ".jpeg");
								} catch (FileNotFoundException e) {
									e.printStackTrace();
								}
							    BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);
							    image.compress(CompressFormat.JPEG, 100, bos);
							    try {
									bos.flush();
								} catch (IOException e) {
									e.printStackTrace();
								}
							    try {
									bos.close();
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}
					numeroFoto=-1;

					}
					if(esitoQuery){
						Intent galleryIntent = new Intent(context, CustomGalleryActivity.class);
						galleryIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
						context.startActivity(galleryIntent);
					}
					else
						activity.runOnUiThread(new Runnable(){
							public void run() {
								balloonView.getProgressBar().setVisibility(View.GONE);
								balloonView.setText("Server momentaneamente non raggiungibile!");
							}
						});
			}
		});
		queryThread.start();
	
		return true;
	}
	
	private void hideBalloon() {
		if (balloonView != null) 
			balloonView.setVisibility(View.GONE);
	}
	
	private void hideOtherBalloons(List<Overlay> overlays) {
		for (Overlay overlay : overlays) 
			if (overlay instanceof MarkerList && overlay != this) 
				((MarkerList) overlay).hideBalloon();
	}
	
	private void setBalloonTouchListener(final int thisIndex) {
		clickRegion.setOnTouchListener(new OnTouchListener() {
			public boolean onTouch(View v, MotionEvent event) {
				View l =  ((View) v.getParent()).findViewById(R.id.balloon_main_layout);
				Drawable d = l.getBackground();
				if (event.getAction() == MotionEvent.ACTION_DOWN) {
					int[] states = {android.R.attr.state_pressed};
					if (d.setState(states)) 
						d.invalidateSelf();
					return true;
				} 
				else if (event.getAction() == MotionEvent.ACTION_UP) {
					int newStates[] = {};
					if (d.setState(newStates)) 
						d.invalidateSelf();
					return true;
				}
				return false;
			}				
		});
	}
	
	private InputStream fetch(String address) throws IOException  {
	    HttpGet httpRequest = new HttpGet(address);
	    HttpResponse response = client.execute(httpRequest);
	    HttpEntity entity = response.getEntity();
	    InputStream instream = entity.getContent();
	    return instream;
	}
	
	private int numeroFoto = -1;
	protected static Thread queryThread; 
	protected static HashMap<String, String> relation;
	private Activity activity;
	private Boolean esitoQuery;
	protected static BalloonOverlay balloonView;
	private View clickRegion;
	private MapView map;
	private Context context;
	private HttpClient client;
	protected static final int MAX = 100;
	private ArrayList<OverlayItem> items = new ArrayList<OverlayItem>();
}